package com.daiyang.lottery.service.impl;
import cn.hutool.crypto.digest.DigestUtil;
import com.daiyang.lottery.service.enums.UserIdentityEnum;
import com.daiyang.lottery.common.errorcode.ServiceErrorCodeConstants;
import com.daiyang.lottery.common.exception.ServiceException;
import com.daiyang.lottery.common.util.JWTUtil;
import com.daiyang.lottery.common.util.RegexUtil;
import com.daiyang.lottery.controller.param.ShortMessageLoginParam;
import com.daiyang.lottery.controller.param.UserLoginParam;
import com.daiyang.lottery.controller.param.UserPasswordLoginParam;
import com.daiyang.lottery.controller.param.UserRegisterParam;
import com.daiyang.lottery.dao.dataobject.Encrypt;
import com.daiyang.lottery.dao.dataobject.UserDO;
import com.daiyang.lottery.dao.mapper.UserMapper;
import com.daiyang.lottery.service.UserService;
import com.daiyang.lottery.service.VerificationCodeService;
import com.daiyang.lottery.service.dto.UserDTO;
import com.daiyang.lottery.service.dto.UserLoginDTO;
import com.daiyang.lottery.service.dto.UserRegisterDTO;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements UserService {
    @Resource (name = "userMapper")
    private UserMapper userMapper;
    @Autowired
    private VerificationCodeService verificationCodeService;
    @Override
    public UserRegisterDTO register(UserRegisterParam userRegisterParam) {
        //用户信息校验
        checkUserRegisterInfo(userRegisterParam);

        //私密数据加密
        UserDO userDO = new UserDO();
        userDO.setUserName(userRegisterParam.getName());
        userDO.setEmail(userRegisterParam.getMail());
        userDO.setPhoneNumber(new Encrypt(userRegisterParam.getPhoneNumber()));
        if(StringUtils.hasText(userRegisterParam.getPassword())){

            // 密码采用sha256加密 hash摘要加密 不可逆
            userDO.setPassword(DigestUtil.sha256Hex(userRegisterParam.getPassword()));
        }
        userDO.setIdentity(userRegisterParam.getIdentity());


        //保存用户信息

        userMapper.insert(userDO);


        //返回结果
        UserRegisterDTO userRegisterDTO = new UserRegisterDTO();
        userRegisterDTO.setUserId(userDO.getId());
        return userRegisterDTO;
    }

    @Override
    public UserLoginDTO login(UserLoginParam userLoginParam) {
         UserLoginDTO userLoginDTO ;
        //校验
        if(userLoginParam instanceof UserPasswordLoginParam  loginParam) {
            userLoginDTO = loginByUserPassword(loginParam);
        } else if(userLoginParam instanceof ShortMessageLoginParam loginParam   ) {
            userLoginDTO = loginByShortMessage(loginParam);
        } else {
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_INFO_NOT_EXIST);
        }
        return userLoginDTO;
    }

    @Override
    public List<UserDTO> findUserList(UserIdentityEnum identity) {
        String identityString = null ==identity ? null : identity.name();
        List<UserDO> userDOList =userMapper.selectUserList(identityString);
        return userDOList.stream()
                .map(userDO->  {
                    UserDTO useDTO =new UserDTO();
                    useDTO.setId(userDO.getId());
                    useDTO.setUserName(userDO.getUserName());
                    useDTO.setEmail(userDO.getEmail());
                    useDTO.setPhoneNumber(userDO.getPhoneNumber().getValue());
                    useDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));
                    return useDTO;
                }).collect(Collectors.toList());
    }

    /**
     * 短息码登录
     * @param loginParam
     * @return
     */
    private UserLoginDTO loginByShortMessage(ShortMessageLoginParam loginParam) {
        UserDO userDO =null;
        if(!RegexUtil.checkMobile(loginParam.getLoginMobile())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        // 获取用户信息
        //校验强制信息登录
        userDO =userMapper.selectByPhoneNumber(new Encrypt(loginParam.getLoginMobile()));
        if(userDO ==null) {
            throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_IS_EMPTY);
        } else if(StringUtils.hasText(loginParam.getMandatoryIdentity())
                && !loginParam.getMandatoryIdentity().equals(userDO.getIdentity())) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }
        String code = verificationCodeService.getVerificationCode(loginParam.getLoginMobile());
        System.out.println("code:"+code);
        if(!loginParam.getVerificationCode().equalsIgnoreCase(code)) {
            throw new ServiceException(ServiceErrorCodeConstants
                    .VERIFICATION_CODE_ERROR);
        }
        //生成token
        Map<String, Object> claim = new HashMap<>();
        claim.put("id", userDO.getId());
        claim.put("identity", userDO.getIdentity());
        String token = JWTUtil.genJwt(claim);

        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));
        return userLoginDTO;
    }

    /**
     * 密码登录
     * @param loginParam
     * @return
     */
    private UserLoginDTO loginByUserPassword(UserPasswordLoginParam loginParam) {
            UserDO userDO =null;
            //判断手机登录还是手机登录
            if(RegexUtil.checkMobile(loginParam.getLoginName())){
                //手机号登录(对手机号进行加密处理)
                userDO =userMapper.selectByPhoneNumber(new Encrypt(loginParam.getLoginName()));
            } else if(RegexUtil.checkMail(loginParam.getLoginName())) {
                //邮箱登录
                userDO = userMapper.selectByEmail(loginParam.getLoginName());
            } else {
                //无此登录方式
                throw new ServiceException(ServiceErrorCodeConstants.LOGIN_NOT_EXIST);
            }
            //校验登录信息

            if(userDO ==null){
                //查无此用户
                throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_IS_EMPTY);
            } else if(StringUtils.hasText(loginParam.getMandatoryIdentity())
                    && !loginParam.getMandatoryIdentity()
                    .equalsIgnoreCase(userDO.getIdentity())){
                //身份验证不通过
                throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
            } else if(StringUtils.hasText(loginParam.getPassword()) //校验密码密码记着加密处理
                    && !DigestUtil.sha256Hex(loginParam.getPassword()).equals(userDO.getPassword())) {

               // System.out.println(DigestUtil.sha256Hex(loginParam.getPassword()));

                //校验不通过
                throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
            }
        //校验成功塞入返回值
        //生成token
        Map<String, Object> claim = new HashMap<>();
        claim.put("id", userDO.getId());
        claim.put("identity", userDO.getIdentity());
        String token = JWTUtil.genJwt(claim);

        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity(UserIdentityEnum.forName(userDO.getIdentity()));
        return userLoginDTO;
    }

    private void checkUserRegisterInfo(UserRegisterParam userRegisterParam) {
        //校验用户信息是否为空
        if (userRegisterParam == null) {
            throw new ServiceException(ServiceErrorCodeConstants.REGISTER_INFO_IS_EMPTY);

        }
        // 校验邮件格式(正则表达式)
        if(!RegexUtil.checkMail(userRegisterParam.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MIAL_ERROR);
        }
        //校验手机号格式
        if(!RegexUtil.checkMobile(userRegisterParam.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        //校验用户身份
        if(null==UserIdentityEnum.forName(userRegisterParam.getIdentity())) {
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }
        //如果是管理员校必须设置密码
        if(UserIdentityEnum.ADMIN.name().equalsIgnoreCase(userRegisterParam.getIdentity())
                && !StringUtils.hasText(userRegisterParam.getPassword())) {
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_IS_EMPTY);
        }
        //校验密码格式
        if(StringUtils.hasText(userRegisterParam.getPassword())
                &&!RegexUtil.checkPassword(userRegisterParam.getPassword())) {
                throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_FORMAT_ERROR);
        }
        //校验邮箱是否已经注册
        if(checkMailUsed(userRegisterParam.getMail())) {
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_IS_USED);
        }


        //校验手机号是否已经注册
        if(checkPhoneNumberUsed(userRegisterParam.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_IS_USED);
        }


    }

    private boolean checkPhoneNumberUsed(String phoneNumber) {
        int count=userMapper.CountByPhoneNumber(new Encrypt(phoneNumber));
        return count>0;
    }

    private boolean checkMailUsed( String mail) {
        int count=userMapper.CountByEmail(mail);
        return count>0;
    }


}
